package linc.cool.framework.protocol.dubbo;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import linc.cool.framework.Invocation;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author yqlin
 * @date 2022/3/11 4:27 下午
 * @description
 */
public class NettyClient {

    public NettyClientHandler client = null;
    private static final ExecutorService executorService = Executors.newCachedThreadPool();

    @SuppressWarnings("unchecked")
    public void start(String hostName, Integer port) {
        client = new NettyClientHandler();
        // 客户端需要一个事件循环组
        EventLoopGroup group = new NioEventLoopGroup();
        // 创建客户端启动对象
        // 注意客户端使用的不是 ServerBootstrap 而是 Bootstrap
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group);
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.TCP_NODELAY, true);
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline pipeline = socketChannel.pipeline();
                pipeline.addLast(new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
                pipeline.addLast(new ObjectEncoder());
                pipeline.addLast(client);
            }
        });
        try {
            // 启动客户端去连接服务器端
            bootstrap.connect(hostName, port).sync();
            System.out.println("Netty Client start");
       } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String send(String hostName, Integer port, Invocation invocation) {
        if (client == null) {
            start(hostName, port);
        }
        client.setInvocation(invocation);
        try {
            return executorService.submit(client).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return null;
    }


}
